#include "MySqlCreateTableStatement.h"

#include "../../../../ast/SQLName.h"
#include "../../../../ast/SQLExpr.h"
#include "../../../../ast/SQLObject.h"
#include "../../../../ast/SQLCommentHint.h"
#include "../../../../ast/expr/SQLIdentifierExpr.h"
#include "../../../../visitor/SQLASTVisitor.h"
#include "../MySqlKey.h"
#include "../../visitor/MySqlASTVisitor.h"
#include "../../../ads/visitor/AdsOutputVisitor.h"
#include "../../../../../utils/StringUtils.h"
#include "../../../../../utils/listAddAll.h"
#include "../../../../../utils/instanceof.h"
#include "../../../../../sql/dialect/mysql/visitor/MySqlShowColumnOutpuVisitor.h"
#include "../../../../../sql/dialect/mysql/ast/statement/MySqlTableIndex.h"
#include "../../../../../sql/dialect/mysql/ast/statement/MySqlRenameTableStatement.h"
#include "../../../../../sql/dialect/mysql/ast/statement/MySqlAlterTableAlterColumn.h"
#include "../../../../../sql/dialect/mysql/ast/statement/MySqlAlterTableChangeColumn.h"
#include "../../../../../sql/ast/statement/SQLAlterTableAddIndex.h"
#include "../../../../../sql/dialect/mysql/ast/MySqlUnique.h"
#include "../../../../../sql/dialect/mysql/ast/statement/MySqlAlterTableOption.h"
#include "../../../../../sql/ast/statement/SQLAlterCharacter.h"
#include "../../../../../sql/ast/statement/SQLSelect.h"
#include "../../../../../sql/ast/statement/SQLColumnDefinition.h"
#include "../../../../../sql/SQLUtils.h"
#include "../../../../../sql/dialect/mysql/ast/statement/MySqlAlterTableModifyColumn.h"
#include "../../../../../sql/dialect/mysql/ast/statement/MySqlExtPartition.h"
#include "../../../../../sql/ast/SQLPartitionBy.h"


SQLName_ptr MySqlCreateTableStatement_TableSpaceOption::getName()
{
  return name;
}

void MySqlCreateTableStatement_TableSpaceOption::setName(SQLName_ptr name)
{
  if (name != NULL)
  {
    name->setParent(SharedObject(MySqlCreateTableStatement_TableSpaceOption));
  }
  this->name = name;
}

SQLExpr_ptr MySqlCreateTableStatement_TableSpaceOption::getStorage()
{
  return storage;
}

void MySqlCreateTableStatement_TableSpaceOption::setStorage(SQLExpr_ptr storage)
{
  if (storage != NULL)
  {
    storage->setParent(SharedObject(MySqlCreateTableStatement_TableSpaceOption));
  }
  this->storage = storage;
}

void MySqlCreateTableStatement_TableSpaceOption::accept0(MySqlASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(MySqlCreateTableStatement_TableSpaceOption)))
  {
    acceptChild(visitor, getName());
    acceptChild(visitor, getStorage());
  }
  visitor->endVisit(SharedObject(MySqlCreateTableStatement_TableSpaceOption));
}

SQLObject_ptr MySqlCreateTableStatement_TableSpaceOption::clone()
{
  SQLObject_ptr clone_tmp = MySqlCreateTableStatement_TableSpaceOption_ptr(new MySqlCreateTableStatement_TableSpaceOption());
  MySqlCreateTableStatement_TableSpaceOption_ptr x = std::dynamic_pointer_cast<MySqlCreateTableStatement_TableSpaceOption>(clone_tmp);
  // MySqlCreateTableStatement_TableSpaceOption *x = new MySqlCreateTableStatement_TableSpaceOption();

  if (name != NULL)
  {
    x->setName(std::dynamic_pointer_cast<SQLName>(name->clone()));
  }

  if (storage != NULL)
  {
    x->setStorage(std::dynamic_pointer_cast<SQLExpr>(storage->clone()));
  }

  return x;
}

SQLObject_list_ptr MySqlCreateTableStatement_TableSpaceOption::getChildren()
{
  return NULL;
}

MySqlCreateTableStatement::MySqlCreateTableStatement()
    : SQLCreateTableStatement(DbType_ptr(new DbType(&DbType::mysql)))
{
  hints = std::make_shared<std::list<SQLCommentHint_ptr>>();
  optionHints = std::make_shared<std::list<SQLCommentHint_ptr>>();
  distributeBy = std::make_shared<std::list<SQLName_ptr>>();
  with = std::make_shared<std::map<string_ptr , SQLName_ptr>>();
}

SQLCommentHint_list_ptr MySqlCreateTableStatement::getHints()
{
  return hints;
}

void MySqlCreateTableStatement::setHints(SQLCommentHint_list_ptr hints)
{
  this->hints->clear(); // = hints;
  Utils::ListAddAll<SQLCommentHint, SQLCommentHint>(hints, this->hints);
}

SQLSelect_ptr MySqlCreateTableStatement::getQuery()
{
  return select;
}

void MySqlCreateTableStatement::setQuery(SQLSelect_ptr query)
{
  this->select = query;
}

void MySqlCreateTableStatement::accept0(SQLASTVisitor_ptr visitor)
{
  if (instanceof <SQLASTVisitor, MySqlASTVisitor>(visitor.get()))
  {
    MySqlASTVisitor_ptr tmp = std::dynamic_pointer_cast<MySqlASTVisitor>(visitor);
    accept0(tmp);
  }
  else if (instanceof <SQLASTVisitor, AdsOutputVisitor>(visitor.get()))
  {
    AdsOutputVisitor_ptr tmp = std::dynamic_pointer_cast<AdsOutputVisitor>(visitor);
    accept0(tmp);
  }
  else
  {
    SQLCreateTableStatement::accept0(visitor);
  }
}

void MySqlCreateTableStatement::accept0(AdsOutputVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(MySqlCreateTableStatement)))
  {
    auto it_hints = hints->begin();
    for (int i = 0; i < hints->size(); i++)
    {
      std::advance(it_hints, i);
      SQLCommentHint_ptr hint = *it_hints;
      if (hint != NULL)
      {
        AdsVisitor_ptr tmp = std::dynamic_pointer_cast<AdsVisitor>(visitor);
        hint->accept(tmp);
      }
    }

    if (tableSource != NULL)
    {
      AdsVisitor_ptr tmp = std::dynamic_pointer_cast<AdsVisitor>(visitor);
      tableSource->accept(tmp);
    }

    auto it_tableElementList = tableElementList->begin();
    for (int i = 0; i < tableElementList->size(); i++)
    {
      std::advance(it_tableElementList, i);
      SQLTableElement_ptr element = *it_tableElementList;
      if (element != NULL)
      {
        AdsVisitor_ptr tmp = std::dynamic_pointer_cast<AdsVisitor>(visitor);
        element->accept(tmp);
      }
    }

    if (like != NULL)
    {
      AdsVisitor_ptr tmp = std::dynamic_pointer_cast<AdsVisitor>(visitor);
      like->accept(tmp);
    }

    if (select != NULL)
    {
      AdsVisitor_ptr tmp = std::dynamic_pointer_cast<AdsVisitor>(visitor);
      select->accept(tmp);
    }
  }
  visitor->endVisit(SharedObject(MySqlCreateTableStatement));
}

void MySqlCreateTableStatement::accept0(MySqlASTVisitor_ptr visitor)
{
  if (visitor->visit(SharedObject(MySqlCreateTableStatement)))
  {
    auto it_hints = hints->begin();
    for (int i = 0; i < hints->size(); i++)
    {
      std::advance(it_hints, i);
      SQLCommentHint_ptr hint = *it_hints;
      if (hint != NULL)
      {
        hint->accept(visitor);
      }
    }

    if (tableSource != NULL)
    {
      tableSource->accept(visitor);
    }

    auto it_tableElementList = tableElementList->begin();
    for (int i = 0; i < tableElementList->size(); i++)
    {
      std::advance(it_tableElementList, i);
      SQLTableElement_ptr element = *it_tableElementList;
      if (element != NULL)
      {
        element->accept(visitor);
      }
    }

    if (like != NULL)
    {
      like->accept(visitor);
    }

    if (select != NULL)
    {
      select->accept(visitor);
    }
  }
  visitor->endVisit(SharedObject(MySqlCreateTableStatement));
}

SQLCommentHint_list_ptr MySqlCreateTableStatement::getOptionHints()
{
  return optionHints;
}

void MySqlCreateTableStatement::setOptionHints(SQLCommentHint_list_ptr optionHints)
{
  this->optionHints = optionHints;
}

SQLName_ptr MySqlCreateTableStatement::getTableGroup()
{
  return tableGroup;
}

void MySqlCreateTableStatement::setTableGroup(SQLName_ptr tableGroup)
{
  this->tableGroup = tableGroup;
}

void MySqlCreateTableStatement::setTableGroup(string_ptr tableGroup)
{
  if (StringUtils::isEmpty(tableGroup))
  {
    this->tableGroup = NULL;
  }
  else
  {
    this->tableGroup = SQLIdentifierExpr_ptr(new SQLIdentifierExpr((tableGroup)));
  }
}

void MySqlCreateTableStatement::simplify()
{
  tableOptions->clear();
  tblProperties->clear();
  SQLCreateTableStatement::simplify();
}

void MySqlCreateTableStatement::showCoumns(std::stringstream * out) /*throws IOException*/
{
  this->accept(MySqlShowColumnOutpuVisitor_ptr(new MySqlShowColumnOutpuVisitor(out)));
  // this->accept(new MySqlShowColumnOutpuVisitor(out));
}

std::shared_ptr<std::list<MySqlKey_ptr>> MySqlCreateTableStatement::getMysqlKeys()
{
  std::shared_ptr<std::list<MySqlKey_ptr>> mySqlKeys = std::make_shared<std::list<MySqlKey_ptr>>();
  for (SQLTableElement_ptr element : *this->getTableElementList())
  {
    if (instanceof <SQLTableElement, MySqlKey>(element))
    {
      mySqlKeys->push_back(std::dynamic_pointer_cast<MySqlKey>(element));
    }
  }
  return mySqlKeys;
}

std::shared_ptr<std::list<MySqlTableIndex_ptr>> MySqlCreateTableStatement::getMysqlIndexes()
{
  std::shared_ptr<std::list<MySqlTableIndex_ptr>> indexList = std::make_shared<std::list<MySqlTableIndex_ptr>>();
  for (SQLTableElement_ptr element : *this->getTableElementList())
  {
    if (instanceof <SQLTableElement, MySqlTableIndex>(element))
    {
      indexList->push_back(std::dynamic_pointer_cast<MySqlTableIndex>(element));
    }
  }
  return indexList;
}

BOOL_ptr MySqlCreateTableStatement::apply(MySqlRenameTableStatement *x)
{
  for (MySqlRenameTableStatement_Item_ptr item : *x->getItems())
  {
    if (apply(item.get()))
    {
      return BOOL::TRUE;
    }
  }

  return BOOL::FALSE;
}

BOOL_ptr MySqlCreateTableStatement::alterApply(SQLAlterTableItem *item)
{
  if (instanceof <SQLAlterTableItem, MySqlAlterTableAlterColumn>(item))
  {
    return apply(dynamic_cast<MySqlAlterTableAlterColumn *>(item));
  }
  else if (instanceof <SQLAlterTableItem, MySqlAlterTableChangeColumn>(item))
  {
    return apply(dynamic_cast<MySqlAlterTableChangeColumn *>(item));
  }
  // else if (item instanceof SQLAlterCharacter *)
  // {
  //     return apply((SQLAlterCharacter *)item);
  // }
  // else if (item instanceof MySqlAlterTableModifyColumn *)
  // {
  //     return apply((MySqlAlterTableModifyColumn *)item);
  // }
  // else if (item instanceof MySqlAlterTableOption *)
  // {
  //     return apply((MySqlAlterTableOption *)item);
  // }

  return SQLCreateTableStatement::alterApply(item);
}

BOOL_ptr MySqlCreateTableStatement::apply(SQLAlterTableAddIndex *item)
{
  SQLName_ptr name = item->getIndexDefinition()->getName();
  if (name != NULL)
  {
    long nameHashCode = name->nameHashCode64();
    auto it_tableElementList = tableElementList->begin();
    for (int i = 0; i < tableElementList->size(); i++)
    {
      SQLTableElement_ptr e = *it_tableElementList;
      if (instanceof <SQLTableElement, MySqlTableIndex>(e))
      {
        SQLName_ptr name1 = (std::dynamic_pointer_cast<MySqlTableIndex>(e))->getName();
        if (name1 != NULL && name1->nameHashCode64() == nameHashCode)
        {
          return BOOL::FALSE;
        }
      }
    }
  }

  if (item->isUnique())
  {
    MySqlUnique_ptr x = MySqlUnique_ptr(new MySqlUnique());
    item->cloneTo(x);
    x->setParent(SharedObject(MySqlCreateTableStatement));
    this->tableElementList->push_back(x);
    return BOOL::TRUE;
  }

  if (item->isKey())
  {
    MySqlKey_ptr x = MySqlKey_ptr(new MySqlKey());
    item->cloneTo(x);
    x->setParent(SharedObject(MySqlCreateTableStatement));
    this->tableElementList->push_back(x);
    return BOOL::TRUE;
  }

  MySqlTableIndex_ptr x = MySqlTableIndex_ptr(new MySqlTableIndex());
  item->cloneTo(x);
  x->setParent(SharedObject(MySqlCreateTableStatement));
  this->tableElementList->push_back(x);
  return BOOL::TRUE;
}

BOOL_ptr MySqlCreateTableStatement::apply(MySqlAlterTableOption *item)
{
  addOption(item->getName(), std::dynamic_pointer_cast<SQLExpr>(item->getValue()));
  return BOOL::TRUE;
}

BOOL_ptr MySqlCreateTableStatement::apply(SQLAlterCharacter *item)
{
  SQLExpr_ptr charset = item->getCharacterSet();
  if (charset != NULL)
  {
    addOption(make_string_ptr("CHARACTER SET"), charset);
  }

  SQLExpr_ptr collate = item->getCollate();
  if (collate != NULL)
  {
    addOption(make_string_ptr("COLLATE"), collate);
  }
  return BOOL::TRUE;
}

BOOL_ptr MySqlCreateTableStatement::apply(MySqlRenameTableStatement_Item *item)
{
  if (!SQLUtils::nameEquals(item->getName(), this->getName()))
  {
    return BOOL::FALSE;
  }
  this->setName(std::dynamic_pointer_cast<SQLName>(item->getTo()->clone()));
  return BOOL::TRUE;
}

BOOL_ptr MySqlCreateTableStatement::apply(MySqlAlterTableAlterColumn *x)
{
  int columnIndex = columnIndexOf(x->getColumn());
  if (columnIndex == -1)
  {
    return BOOL::FALSE;
  }

  SQLExpr_ptr defaultExpr = x->getDefaultExpr();
  auto it_tableElementList = tableElementList->begin();
  std::advance(it_tableElementList, columnIndex);
  SQLColumnDefinition_ptr column = std::dynamic_pointer_cast<SQLColumnDefinition>(*it_tableElementList);

  if (x->isDropDefault())
  {
    column->setDefaultExpr(NULL);
  }
  else if (defaultExpr != NULL)
  {
    column->setDefaultExpr(defaultExpr);
  }

  return BOOL::TRUE;
}

BOOL_ptr MySqlCreateTableStatement::apply(MySqlAlterTableChangeColumn *item)
{
  SQLName_ptr columnName = item->getColumnName();
  int columnIndex = columnIndexOf(columnName);
  if (columnIndex == -1)
  {
    return BOOL::FALSE;
  }

  int afterIndex = columnIndexOf(item->getAfterColumn());
  int beforeIndex = columnIndexOf(item->getFirstColumn());

  int insertIndex = -1;
  if (beforeIndex != -1)
  {
    insertIndex = beforeIndex;
  }
  else if (afterIndex != -1)
  {
    insertIndex = afterIndex + 1;
  }
  else if (item->isFirst())
  {
    insertIndex = 0;
  }

  SQLColumnDefinition_ptr column = std::dynamic_pointer_cast<SQLColumnDefinition>(item->getNewColumnDefinition()->clone());
  column->setParent(SharedObject(MySqlCreateTableStatement));
  auto it_tableElementList = tableElementList->begin();
  if (insertIndex == -1 || insertIndex == columnIndex)
  {
    std::advance(it_tableElementList, columnIndex);
    tableElementList->insert(it_tableElementList, column);
  }
  else
  {
    if (insertIndex > columnIndex)
    {
      std::advance(it_tableElementList, insertIndex);
      tableElementList->insert(it_tableElementList, column);
      std::advance(it_tableElementList, columnIndex);
      // tableElementList->remove(columnIndex);
      if (it_tableElementList != tableElementList->end())
        tableElementList->erase(it_tableElementList);
    }
    else
    {
      std::advance(it_tableElementList, columnIndex);
      if (it_tableElementList != tableElementList->end())
        tableElementList->erase(it_tableElementList);
      // tableElementList->remove(columnIndex);
      std::advance(it_tableElementList, insertIndex);
      tableElementList->insert(it_tableElementList, column);
      // tableElementList->add(insertIndex, column);
    }
  }

  // auto it_tableElementList = tableElementList->begin();
  for (int i = 0; i < tableElementList->size(); i++)
  {
    std::advance(it_tableElementList, i);
    SQLTableElement_ptr e = *it_tableElementList;
    if (instanceof <SQLTableElement, MySqlTableIndex>(e))
    {
      (std::dynamic_pointer_cast<MySqlTableIndex>(e)->applyColumnRename(columnName, column.get()));
    }
    else if (instanceof <SQLTableElement, SQLUnique>(e))
    {
      SQLUnique_ptr unique = std::dynamic_pointer_cast<SQLUnique>(e);
      unique->applyColumnRename(columnName, column.get());
    }
  }

  return BOOL::TRUE;
}

BOOL_ptr MySqlCreateTableStatement::apply(MySqlAlterTableModifyColumn *item)
{
  SQLColumnDefinition_ptr column = std::dynamic_pointer_cast<SQLColumnDefinition>(item->getNewColumnDefinition()->clone());
  SQLName_ptr columnName = column->getName();

  int columnIndex = columnIndexOf(columnName);
  if (columnIndex == -1)
  {
    return BOOL::FALSE;
  }

  int afterIndex = columnIndexOf(item->getAfterColumn());
  int beforeIndex = columnIndexOf(item->getFirstColumn());

  int insertIndex = -1;
  if (beforeIndex != -1)
  {
    insertIndex = beforeIndex;
  }
  else if (afterIndex != -1)
  {
    insertIndex = afterIndex + 1;
  }

  if (item->isFirst())
  {
    insertIndex = 0;
  }

  column->setParent(SharedObject(MySqlCreateTableStatement));
  auto it_tableElementList = tableElementList->begin();
  if (insertIndex == -1 || insertIndex == columnIndex)
  {
    std::advance(it_tableElementList, columnIndex);
    tableElementList->insert(it_tableElementList, column);
    return BOOL::TRUE;
  }
  else
  {
    if (insertIndex > columnIndex)
    {
      std::advance(it_tableElementList, columnIndex);
      tableElementList->insert(it_tableElementList, column);
      // tableElementList->remove(columnIndex);
      std::advance(it_tableElementList, columnIndex);
      if (it_tableElementList != tableElementList->end())
        tableElementList->erase(it_tableElementList);
    }
    else
    {
      // tableElementList->remove(columnIndex);
      std::advance(it_tableElementList, columnIndex);
      if (it_tableElementList != tableElementList->end())
        tableElementList->erase(it_tableElementList);
      std::advance(it_tableElementList, insertIndex);
      tableElementList->insert(it_tableElementList, column);
    }
  }

  // Check key length like change.
  // Just old name -> old name.
  for (int i = 0; i < tableElementList->size(); i++)
  {
    std::advance(it_tableElementList, i);
    SQLTableElement_ptr e = *it_tableElementList;
    if (instanceof <SQLTableElement, MySqlTableIndex>(e))
    {
      (std::dynamic_pointer_cast<MySqlTableIndex>(e))->applyColumnRename(columnName, column.get());
    }
    else if (instanceof <SQLTableElement, SQLUnique>(e))
    {
      SQLUnique_ptr unique = std::dynamic_pointer_cast<SQLUnique>(e);
      unique->applyColumnRename(columnName, column.get());
    }
  }

  return BOOL::TRUE;
}

void MySqlCreateTableStatement::cloneTo(MySqlCreateTableStatement_ptr x)
{
  SQLCreateTableStatement::cloneTo(x);
  if (partitioning != NULL)
  {
    x->setPartitioning(std::dynamic_pointer_cast<SQLPartitionBy>(partitioning->clone()));
  }
  if (localPartitioning != NULL)
  {
    x->setLocalPartitioning(std::dynamic_pointer_cast<SQLPartitionBy>(localPartitioning->clone()));
  }
  for (SQLCommentHint_ptr hint : *hints)
  {
    SQLCommentHint_ptr h2 = std::dynamic_pointer_cast<SQLCommentHint>(hint->clone());
    h2->SQLObjectImpl::setParent(x);
    x->hints->push_back(h2);
  }
  for (SQLCommentHint_ptr hint : *optionHints)
  {
    SQLCommentHint_ptr h2 = std::dynamic_pointer_cast<SQLCommentHint>(hint->clone());
    h2->SQLObjectImpl::setParent(x);
    x->optionHints->push_back(h2);
  }
  if (like != NULL)
  {
    x->setLike(std::dynamic_pointer_cast<SQLExprTableSource>(like->clone()));
  }
  if (tableGroup != NULL)
  {
    x->setTableGroup(std::dynamic_pointer_cast<SQLName>(tableGroup->clone()));
  }

  if (dbPartitionBy != NULL)
  {
    x->setDbPartitionBy(std::dynamic_pointer_cast<SQLExpr>(dbPartitionBy->clone()));
  }

  if (dbPartitions != NULL)
  {
    x->setDbPartitionBy(std::dynamic_pointer_cast<SQLExpr>(dbPartitions->clone()));
  }

  if (tablePartitionBy != NULL)
  {
    x->setTablePartitionBy(std::dynamic_pointer_cast<SQLExpr>(tablePartitionBy->clone()));
  }

  if (tablePartitions != NULL)
  {
    x->setTablePartitions(std::dynamic_pointer_cast<SQLExpr>(tablePartitions->clone()));
  }

  if (exPartition != NULL)
  {
    x->setExPartition(std::dynamic_pointer_cast<MySqlExtPartition>(exPartition->clone()));
  }

  if (archiveBy != NULL)
  {
    x->setArchiveBy(std::dynamic_pointer_cast<SQLName>(archiveBy->clone()));
  }

  if (distributeByType != NULL)
  {
    x->setDistributeByType(std::dynamic_pointer_cast<SQLName>(distributeByType->clone()));
  }

  if (distributeByType != NULL)
  {
    for (SQLName_ptr sqlName : *distributeBy)
    {
      x->getDistributeBy()->push_back(std::dynamic_pointer_cast<SQLName>(sqlName->clone()));
    }
  }
}

SQLObject_ptr MySqlCreateTableStatement::clone()
{
  SQLObject_ptr clone_tmp = MySqlCreateTableStatement_ptr(new MySqlCreateTableStatement());
  MySqlCreateTableStatement_ptr x = std::dynamic_pointer_cast<MySqlCreateTableStatement>(clone_tmp);
  // MySqlCreateTableStatement *x = new MySqlCreateTableStatement();
  cloneTo(x);
  return x;
}

SQLExpr_ptr MySqlCreateTableStatement::getDbPartitionBy()
{
  return dbPartitionBy;
}

void MySqlCreateTableStatement::setDbPartitionBy(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(MySqlCreateTableStatement));
  }
  this->dbPartitionBy = x;
}

SQLExpr_ptr MySqlCreateTableStatement::getTablePartitionBy()
{
  return tablePartitionBy;
}

void MySqlCreateTableStatement::setTablePartitionBy(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(MySqlCreateTableStatement));
  }
  this->tablePartitionBy = x;
}

SQLName_ptr MySqlCreateTableStatement::getDistributeByType()
{
  return distributeByType;
}

void MySqlCreateTableStatement::setDistributeByType(SQLName_ptr distributeByType)
{
  this->distributeByType = distributeByType;
}

SQLName_list_ptr MySqlCreateTableStatement::getDistributeBy()
{
  return distributeBy;
}

SQLExpr_ptr MySqlCreateTableStatement::getTbpartitions()
{
  return tablePartitions;
}

SQLExpr_ptr MySqlCreateTableStatement::getTablePartitions()
{
  return tablePartitions;
}

void MySqlCreateTableStatement::setTablePartitions(SQLExpr_ptr x)
{
  this->tablePartitions = x;
}

SQLExpr_ptr MySqlCreateTableStatement::getDbpartitions()
{
  return dbPartitions;
}

void MySqlCreateTableStatement::setDbPartitions(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(MySqlCreateTableStatement));
  }
  this->dbPartitions = x;
}

MySqlExtPartition_ptr MySqlCreateTableStatement::getExtPartition()
{
  return exPartition;
}

void MySqlCreateTableStatement::setExPartition(MySqlExtPartition_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(MySqlCreateTableStatement));
  }
  this->exPartition = x;
}

SQLExpr_ptr MySqlCreateTableStatement::getDbPartitions()
{
  return dbPartitions;
}

SQLName_ptr MySqlCreateTableStatement::getStoredBy()
{
  return storedBy;
}

void MySqlCreateTableStatement::setStoredBy(SQLName_ptr storedBy)
{
  this->storedBy = storedBy;
}

std::shared_ptr<std::map<string_ptr, SQLName_ptr>> MySqlCreateTableStatement::getWith()
{
  return with;
}

BOOL_ptr MySqlCreateTableStatement::isBroadCast()
{
  return isBroadCast_;
}

void MySqlCreateTableStatement::setBroadCast(BOOL_ptr broadCast)
{
  isBroadCast_ = broadCast;
}

SQLName_ptr MySqlCreateTableStatement::getArchiveBy()
{
  return archiveBy;
}

void MySqlCreateTableStatement::setArchiveBy(SQLName_ptr archiveBy)
{
  this->archiveBy = archiveBy;
}

BOOL_ptr MySqlCreateTableStatement::getWithData()
{
  return withData;
}

void MySqlCreateTableStatement::setWithData(BOOL_ptr withData)
{
  this->withData = withData;
}

SQLExpr_ptr MySqlCreateTableStatement::getEngine()
{
  for (SQLAssignItem_ptr option : *tableOptions)
  {
    SQLExpr_ptr target = option->getTarget();
    if (instanceof <SQLExpr, SQLIdentifierExpr>(target) &&
                       StringUtils::iequals(*((std::dynamic_pointer_cast<SQLIdentifierExpr>(target))->getName()), "ENGINE"))
    {
      return option->getValue();
    }
  }

  return NULL;
}

void MySqlCreateTableStatement::setEngine(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(MySqlCreateTableStatement));
  }
  addOption(make_string_ptr("ENGINE"), x);
}

void MySqlCreateTableStatement::setPageChecksum(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(MySqlCreateTableStatement));
  }
  addOption(make_string_ptr("PAGE_CHECKSUM"), x);
}

void MySqlCreateTableStatement::setTransactional(SQLExpr_ptr x)
{
  if (x != NULL)
  {
    x->setParent(SharedObject(MySqlCreateTableStatement));
  }
  addOption(make_string_ptr("TRANSACTIONAL"), x);
}
